﻿package component.tree.service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class TreeOrder implements ITreeOrder {
	
	private String idName = "id"; 
	private String parentIdName = "parentId"; 
	private String orderName = "index";
	private String orderFlag = "index";
	private String levelName = "level"; 

	private List dataList = null;
	
	public TreeOrder(){
		
	}
	public TreeOrder(String[] treeName){
		this.idName = treeName[0];
		this.parentIdName = treeName[1];
		this.orderName = treeName[2];
		this.levelName = treeName[3];
	}
	public TreeOrder(String[] treeName,String orderFlag){
		this.idName = treeName[0];
		this.parentIdName = treeName[1];
		this.orderName = treeName[2];
		this.levelName = treeName[3];
		this.orderFlag = orderFlag;
	}
	
	public List orderTree(List treeList){
		if (treeList == null || treeList.isEmpty()){
			return new ArrayList();
		}
		this.dataList = treeList;
		String rootId = this.getRootId(treeList);
		return this.getOrderTreeList(rootId);
	}

	public List getOrderTreeList(String id) {
		List levelList = new ArrayList();
		List delList = new ArrayList();
		List treeList = new ArrayList();
		if (dataList == null || dataList.isEmpty())
			return treeList;
		Iterator it = dataList.iterator();
		try {
			while (it.hasNext()) {
				Object o = (Object) it.next();
				Field idField = o.getClass().getDeclaredField(parentIdName);
				if (idField.isAccessible() == false)
					idField.setAccessible(true);
				if (id.equals(idField.get(o).toString())) {
					levelList.add(o);
					delList.add(o);
				}

			}

			if (delList.size() != 0) {
				dataList.removeAll(delList);
				levelList = OrderByLevel(levelList);
				Iterator leveIt = levelList.iterator();
				while (leveIt.hasNext()) {
					Object o = (Object) leveIt.next();
					treeList.add(o);

					Field idField = o.getClass().getDeclaredField(idName);
					if (idField.isAccessible() == false)
						idField.setAccessible(true);
					List tList = this.getOrderTreeList(idField.get(o).toString());
					Iterator ittree = tList.iterator();
					while (ittree.hasNext()) {
						treeList.add(ittree.next());
					}
				}

			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return treeList;

	}
	
	public List OrderByLevel(List levelList){
		if(this.orderFlag.equals("index")){
			return this.OrderByIndex(levelList);
		}
		if(this.orderFlag.equals("code")){
			return this.OrderByCode(levelList);
		}else{
			return this.OrderByString(levelList);
		}
	}

	public List OrderByIndex(List levelList){
		int len = levelList.size();
		if (len == 0)
			return levelList;
		Map map = new HashMap();
		
		try{
			for (int i = 0; i < len; i++) {
				Object o = (Object) levelList.get(i);
				Field idField = o.getClass().getDeclaredField(idName);
				Field orderField = o.getClass().getDeclaredField(orderName);
				idField.setAccessible(true);
				orderField.setAccessible(true);
	
				List list = (List) map.get(orderField.get(o).toString());
				if (list == null) list = new ArrayList();
				list.add(o);
				map.put(orderField.get(o).toString(), list);
	
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		
		Object[] keyArr = (Object[]) map.keySet().toArray();
		Long orderArr[] = new Long[keyArr.length];
		len = keyArr.length;
		for (int i = 0; i < len; i++) {
			orderArr[i] = Long.valueOf(String.valueOf(keyArr[i]));
		}
		Arrays.sort(orderArr);
		List oList = new ArrayList();
		for (int i = 0; i < len; i++) {
			List list = (List) map.get(orderArr[i].toString());
			if(list!=null){
				Iterator iter = list.iterator();
				while (iter.hasNext()) {
					oList.add(iter.next());
				}
			}
			
		}
		return oList;
	}
	

	public List OrderByCode(List levelList){
		int len = levelList.size();
		if (len == 0)
			return levelList;
		Map map = new HashMap();
		Map codeMap = new HashMap();
		
		try{
			for (int i = 0; i < len; i++) {
				Object o = (Object) levelList.get(i);
				Field idField = o.getClass().getDeclaredField(orderName);
				Field orderField = o.getClass().getDeclaredField(orderName);
				idField.setAccessible(true);
				orderField.setAccessible(true);
	
				List list = (List) map.get(orderField.get(o).toString());
				if (list == null) list = new ArrayList();
				list.add(o);
				map.put(orderField.get(o).toString(), list);
	
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		
		Object[] keyArr = (Object[]) map.keySet().toArray();
		Long orderArr[] = new Long[keyArr.length];
		len = keyArr.length;
		for (int i = 0; i < len; i++) {
			String code = String.valueOf(keyArr[i]);
			orderArr[i] = Long.valueOf(code);
			codeMap.put(orderArr[i], code);
		}
		Arrays.sort(orderArr);
		List oList = new ArrayList();
		for (int i = 0; i < len; i++) {
			List list = (List) map.get(codeMap.get(orderArr[i]));
			if(list!=null){
				Iterator iter = list.iterator();
				while (iter.hasNext()) {
					oList.add(iter.next());
				}
			}
			
		}
		return oList;
	}
	
	public List OrderByString(List levelList){
		int len = levelList.size();
		if (len == 0)
			return levelList;
		Map map = new HashMap();
		
		try{
			for (int i = 0; i < len; i++) {
				Object o = (Object) levelList.get(i);
				Field idField = o.getClass().getDeclaredField(idName);
				Field orderField = o.getClass().getDeclaredField(orderName);
				idField.setAccessible(true);
				orderField.setAccessible(true);
	
				List list = (List) map.get(orderField.get(o).toString());
				if (list == null) list = new ArrayList();
				list.add(o);
				map.put(orderField.get(o).toString(), list);
	
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		
		Object[] keyArr = (Object[]) map.keySet().toArray();
		String orderArr[] = new String[keyArr.length];
		len = keyArr.length;
		for (int i = 0; i < len; i++) {
			orderArr[i] = String.valueOf(keyArr[i]);
		}
		Arrays.sort(orderArr);
		List oList = new ArrayList();
		for (int i = 0; i < len; i++) {
			List list = (List) map.get(orderArr[i]);
			if(list!=null){
				Iterator iter = list.iterator();
				while (iter.hasNext()) {
					oList.add(iter.next());
				}
			}
			
		}
		return oList;
	}
	
	public String getRootId(List treeList) {
		Iterator it = treeList.iterator();
		Integer level = null;
		String rootId = null;
		try {
			while (it.hasNext()) {
				Object o = (Object) it.next();
				Field levelField = o.getClass().getDeclaredField(levelName);
				levelField.setAccessible(true);
				int level2 = Integer.valueOf(String.valueOf(levelField.get(o))).intValue();
				if (level == null || level2 < level.intValue()) {
					Field rootField = o.getClass().getDeclaredField(parentIdName);
					rootField.setAccessible(true);
					level = Integer.valueOf(levelField.get(o).toString());
					rootId = rootField.get(o).toString();
					rootField.setAccessible(false);
				}
				levelField.setAccessible(false);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("rootId = " + rootId);
		return rootId;
	}

}
